﻿using System;
using System.Drawing;
using ICSharpCode.TextEditor;
using ICSharpCode.TextEditor.Addons;
using ICSharpCode.TextEditor.Document;
using System.Windows.Forms;
using System.Text.RegularExpressions;

namespace Tapioca.Views
{
	public class XmlTextEditorBase : TextEditorControl
	{
        private int previousSearchLine = -1;
        private int previousSearchWord;

		// Methods
		public XmlTextEditorBase()
		{
			base.Document.HighlightingStrategy = HighlightingStrategyFactory.CreateHighlightingStrategy("XML");
			base.Document.FoldingManager.FoldingStrategy = new XmlFoldingStrategy();
			base.Document.FormattingStrategy = new XmlFormattingStrategy();
			base.TextEditorProperties = InitializeProperties();
			base.Document.FoldingManager.UpdateFoldings(string.Empty, null);
			base.TextArea.Refresh(base.TextArea.FoldMargin);

            base.Document.FoldingManager.UpdateFoldings(string.Empty, null);
            base.TextArea.Refresh(base.TextArea.FoldMargin);
		}


		private static ITextEditorProperties InitializeProperties()
		{
			var properties = new DefaultTextEditorProperties();
			properties.Font = new Font("Courier new", 9, FontStyle.Regular);
			properties.IndentStyle = IndentStyle.Smart;
			properties.ShowSpaces = false;
			properties.LineTerminator = Environment.NewLine;
			properties.ShowTabs = false;
			properties.ShowInvalidLines = false;
			properties.ShowEOLMarker = false;
			properties.TabIndent = 2;
			properties.CutCopyWholeLine = true;
			properties.LineViewerStyle = LineViewerStyle.None;
			properties.MouseWheelScrollDown = true;
			properties.MouseWheelTextZoom = true;
			properties.AllowCaretBeyondEOL = false;
			properties.AutoInsertCurlyBracket = true;
			properties.BracketMatchingStyle = BracketMatchingStyle.After;
			properties.ConvertTabsToSpaces = false;
			properties.ShowMatchingBracket = true;
			properties.EnableFolding = true;
			properties.ShowVerticalRuler = false;
			properties.IsIconBarVisible = true;
			properties.Encoding = System.Text.Encoding.Unicode;
			properties.UseAntiAliasedFont = false;
			return properties;
		}


        public void Find(string search)
        {
            this.Find(search, false);
        }

        public void Find(string search, bool caseSensitive)
        {
            var found = false;

            var i = 0;
            var lines = base.Text.Split(new[] { "\r\n" }, StringSplitOptions.None); 
            foreach (var line in lines)
            {
                if (i > previousSearchLine)
                {
                    int start;
                    if (previousSearchWord > line.Length)
                    {
                        start = caseSensitive ?
                            line.IndexOf(search) :
                            line.ToLower().IndexOf(search.ToLower());

                        previousSearchWord = 0;
                    }
                    else
                    {
                        start = caseSensitive ?
                            line.IndexOf(search, previousSearchWord) :
                            line.ToLower().IndexOf(search.ToLower(), previousSearchWord);
                    }
                    var end = start + search.Length;
                    if (start != -1)
                    {
                        var p1 = new Point(start, i);
                        var p2 = new Point(end, i);

                        base.TextArea.SelectionManager.SetSelection(p1, p2);
                        base.ActiveTextAreaControl.ScrollTo(i);
                        base.Refresh();

                        previousSearchWord = end;
                        previousSearchLine = i - 1;
                        found = true;
                        break;
                    }

                    previousSearchWord = 0;
                }

                i += 1;
                if (i >= lines.Length - 1)
                {
                    previousSearchLine = -1;
                }
            }

            if (!found)
            {
                MessageBox.Show("The following specified text was not found: " + Environment.NewLine + Environment.NewLine + search);
            }
        }


        public void Replace(string search, string replace, bool caseSensitive)
        {
            if (base.TextArea.SelectionManager.HasSomethingSelected && base.TextArea.SelectionManager.SelectedText == search)
            {
                var text = base.TextArea.SelectionManager.SelectedText;
                base.TextArea.Caret.Position = base.TextArea.SelectionManager.SelectionCollection[0].StartPosition;
                base.TextArea.SelectionManager.ClearSelection();
                base.TextArea.Document.Replace(base.TextArea.Caret.Offset, text.Length, replace);
                return;
            }

            this.Find(search, caseSensitive);
        }

        public void ReplaceAll(string search, string replace)
        {
            this.ReplaceAll(search, replace, false);
        }

        public void ReplaceAll(string search, string replace, bool caseSensitive)
        {
            base.Text = Regex.Replace(base.Text, search, replace, caseSensitive ? RegexOptions.None : RegexOptions.IgnoreCase);
            base.Refresh();
        }
	}
}
